#pragma once

#include "Socket.hpp"
#include "Logger.hpp"
#include "common.hpp"

#include <thread>

using namespace SocketModule;

class TcpServer
{
    static const uint16_t default_port = 0;
    typedef function<string(string &)> Handle_t;

    void IOService(SockPtr sock) // 网络IO服务
    {
        string recvbuf; // 用户级接收缓冲区
        string sendbuf; // 用户级发送缓冲区

        while (true)
        {
            // 读取请求
            string in;
            int n = sock->Recv(in);
            if (n > 0)
            {
                LOG(LogLevel::DEBUG) << "成功读取请求，sockfd: " << sock->GetSockfd() << "\r\n"
                                     << in;
                recvbuf += in;
            }
            else if (n == 0)
            {
                LOG(LogLevel::DEBUG) << "客户端断开连接,sockfd: " << sock->GetSockfd();
                sock->Close(); // 关闭fd,防止fd泄漏
                return;        // 线程退出
            }
            else
            {
                LOG(LogLevel::WARNING) << "sockfd: " << sock->GetSockfd() << " recv error";
                sock->Close(); // 关闭fd,防止fd泄漏
                return;        // 线程退出
            }

            string tmp;
            // 把接收缓冲区中的内容交付给上层
            if (_handle_request != nullptr)
            {
                LOG(LogLevel::DEBUG) <<"sockfd: " << sock->GetSockfd()<< " 把接收缓冲区中的内容交付给上层，进入HttpServer: HandleRequest";
                tmp = _handle_request(recvbuf);
            }

            if (tmp.empty()) // 如果tmp为空，则表示接收缓冲区中一份完整的报文都凑不出来
            {
                LOG(LogLevel::DEBUG) <<"sockfd: " << sock->GetSockfd()<<"没能获得Resp,重新recv";
                continue; // 重新循环，再去recv
            }

            // 把上层序列化好的response添加到发送缓冲区
            sendbuf += tmp;

            // 发送用户级发送缓冲区中的数据
            n = sock->Send(sendbuf);
            if (n > 0) // 发送成功
            {
                LOG(LogLevel::DEBUG) <<"sockfd: " << sock->GetSockfd()<< "发送成功";
                sendbuf.erase(0, n); // 从用户级缓冲区中去除发送出去的数据
            }
            else if (n == 0)
            {
                LOG(LogLevel::DEBUG) << "客户端断开连接,sockfd: " << sock->GetSockfd();
                sock->Close(); // 关闭fd,防止fd泄漏
                return;        // 线程退出
            }
            else
            {
                LOG(LogLevel::WARNING) << "sockfd: " << sock->GetSockfd() << " send error";
                sock->Close(); // 关闭fd,防止fd泄漏
                return;        // 线程退出
            }
        }
    }

public:
    TcpServer(uint16_t port = default_port)
        : _port(port),
          _listensocket(make_shared<TcpSocket>(port)),
          _isrunning(false),
          _handle_request(nullptr)
    {
        // 创建ListenSocket
        _listensocket->BuildSocket(SockType::LISTEN_SOCK);
    }

    void Registered(Handle_t hand)
    {
        _handle_request = hand;
    }
    void Start()
    {
        if (_isrunning == true) // 别重复启动
        {
            return;
        }

        LOG(LogLevel::DEBUG) << "TcpServer启动";
        _isrunning = true;
        while (_isrunning)
        {
            // 获取新连接
            uint32_t client_ip;
            uint16_t client_port;
            SockPtr sock = _listensocket->Accept(client_ip, client_port);

            // 打印日志
            char ip_buf[100] = {0};
            uint32_t inet_ip = htonl(client_ip);
            inet_ntop(AF_INET, &inet_ip, ip_buf, sizeof(ip_buf));

            LOG(LogLevel::DEBUG) << "成功连接客户端:ip: " << ip_buf << "  port: " << client_port
                                 << " sockfd: " << sock->GetSockfd();

            // 连接管理--多线程
            thread t([this, sock]()
                     { this->IOService(sock); });

            t.detach(); // 线程分离
        }
        _isrunning = false;
    }
    void Stop()
    {
        _isrunning = false;
    }
    ~TcpServer()
    {
        _listensocket->Close();
    }

private:
    uint16_t _port;
    SockPtr _listensocket;
    bool _isrunning; // 是否运行

    Handle_t _handle_request;
};
